import {CancelConfig} from '../config/CancelConfig'

const coefficient = CancelConfig.coefficient;  //限制斜率
const distanceLimit = CancelConfig.distanceLimit;  //限制曲线扭曲程度
const lineTerminalDistanceLimit = CancelConfig.lineTerminalDistanceLimit;

function calculatePTPDistance(pointA, pointB) {  //点到点距离
    return Math.sqrt(((pointA.x - pointB.x) * (pointA.x - pointB.x)) + ((pointA.y - pointB.y) * (pointA.y - pointB.y)))
}

function calculatePTLDistance(point, line) {  //点到线距离
    return Math.abs(point.x * line.a - point.y + line.b) / Math.sqrt(line.a * line.a + 1)
}

function cheapLine(pointA, pointB) {  //简易求直线
    let a = (pointA.y - pointB.y) / (pointA.x - pointB.x);
    let b = pointA.y - a * pointA.x;
    return {a, b}
}

function determinant(v1, v2, v3, v4) {  //计算行列式
    return (v1 * v3 - v2 * v4);
}

function checkIntersect(a, b, c, d) {  //判断线段是否相交
    let u = (c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y),
        v = (d.x - a.x) * (b.y - a.y) - (b.x - a.x) * (d.y - a.y),
        w = (a.x - c.x) * (d.y - c.y) - (d.x - c.x) * (a.y - c.y),
        z = (b.x - c.x) * (d.y - c.y) - (d.x - c.x) * (b.y - c.y);
    return (u * v <= 0.00000001 && w * z <= 0.00000001);
}


function checkIntersectThreeLineVersion(a, b, c, d, e, f) {
    return checkIntersect(a, b, c, d) || checkIntersect(a, b, e, f) || checkIntersect(c, d, e, f)
}

class tripleLine {

    constructor() {

        this.stuStrMap = new Map();
    }

    /*方法说明
     *@method checkDotArray
     *@for tripleLine
     *@param {Array} newDotArray 新增笔画
     *@param {Number} stuId 学生标识
     *@param {Number} questionId 题目标识
     *@param {Number} selectBoxIndex 多选框索引
     *@return {Boolean} 三点集是否构成三横线
    */
    checkDotArray(newDotArray, stuId = 0, questionId = 0, selectBoxIndex = -1 ) {
        console.log('enter');
        let key = stuId + '-' + questionId + '-' + selectBoxIndex + '-data';
        let storeData = this.stuStrMap.get(key);
        let lastDotArray, preDotArray;
        if (!storeData) {
            this.stuStrMap.set(key, {preDotArray: newDotArray, lastDotArray: []});
            return false
        }

        if (!(storeData.lastDotArray && storeData.preDotArray)) {
            this.stuStrMap.set(key, {
                preDotArray: newDotArray ? newDotArray : [],
                lastDotArray: storeData.preDotArray ? storeData.preDotArray : []
            });
            return false;

        }

        lastDotArray = storeData.lastDotArray;
        preDotArray = storeData.preDotArray;

        this.stuStrMap.set(key, {
            preDotArray: newDotArray ? newDotArray : [],
            lastDotArray: preDotArray ? preDotArray : []
        });

        if (lastDotArray.length < 3 || newDotArray.length < 3 || preDotArray.length < 3) return false;

        let A = lastDotArray[0], B = lastDotArray[lastDotArray.length - 1],
            C = preDotArray[0], D = preDotArray[preDotArray.length - 1],
            E = newDotArray[0], F = newDotArray[newDotArray.length - 1];
        let isIntersected = checkIntersectThreeLineVersion(A, B, C, D, E, F);

        if (isIntersected) {  //线段是否相交
            return false
        }

        /******************************************  newDotArray  *******************************/
        let line3 = cheapLine(E, F);

        if (Math.abs(line3.a) > coefficient) return false;

        let d3 = calculatePTPDistance(E, F);
        for (let point of newDotArray) {
            let thisDis = (calculatePTLDistance(point, line3));
            if ((thisDis / d3) > distanceLimit) {
                this.stuStrMap.set(key, {newDotArray: [], preDotArray: []});
                return false
            }
        }

        /******************************************  preDotArray  *******************************/
        let line2 = cheapLine(C, D);

        if (Math.abs(line2.a) > coefficient) return false;

        let d2 = calculatePTPDistance(C, D);
        for (let point of preDotArray) {
            let thisDis = (calculatePTLDistance(point, line2));
            if ((thisDis / d2) > distanceLimit) {
                this.stuStrMap.set(key, {
                    lastDotArray: [],
                    preDotArray: newDotArray ? newDotArray : []
                });
                return false
            }
        }

        /******************************************  lastDotArray  *******************************/
        let line1 = cheapLine(A, B);

        if (Math.abs(line1.a) > coefficient) return false;

        let d1 = calculatePTPDistance(A, B);
        for (let point of lastDotArray) {
            let thisDis = (calculatePTLDistance(point, line1));
            if ((thisDis / d1) > distanceLimit) {
                return false
            }
        }

        let checkEndPoint = function (PA, PB, PC, PD) {
            return (PA.x < PC.x && PC.x < PB.x) || (PA.x < PD.x && PD.x < PB.x) || (PC.x < PA.x && PA.x < PD.x) || (PC.x < PB.x && PB.x < PD.x)
        }, caculatePTPDistance = calculatePTPDistance;

        return ((checkEndPoint(A, B, C, D) && (checkEndPoint(A, B, E, F) || checkEndPoint(C, D, E, F)))
            || (checkEndPoint(C, D, E, F) && (checkEndPoint(A, B, C, D) || checkEndPoint(A, B, E, F)))
            || (checkEndPoint(A, B, E, F) && (checkEndPoint(A, B, C, D) || checkEndPoint(C, D, E, F))))
            && ((caculatePTPDistance(E, A) <= lineTerminalDistanceLimit || caculatePTPDistance(E, B) <= lineTerminalDistanceLimit) && (caculatePTPDistance(E, C) <= lineTerminalDistanceLimit || caculatePTPDistance(E, D) <= lineTerminalDistanceLimit)
                || (caculatePTPDistance(F, A) <= lineTerminalDistanceLimit || caculatePTPDistance(F, B) <= lineTerminalDistanceLimit) && (caculatePTPDistance(F, C) <= lineTerminalDistanceLimit || caculatePTPDistance(F, D) <= lineTerminalDistanceLimit))

    }
}

/*************************************************计算方法END***********************************************/
export default new tripleLine
